package com.egor.views.components.modalboxes;

import com.egor.data.entity.Department;
import com.vaadin.flow.component.ComponentEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.ValidationException;
import com.vaadin.flow.shared.Registration;
import com.vaadin.flow.spring.annotation.RouteScope;
import lombok.Getter;
import org.springframework.stereotype.Component;

import java.time.LocalDate;

@RouteScope
@Component
public class EditDepartmentModalBox extends Dialog {
    private Department department;
    private final VerticalLayout layout = new VerticalLayout();
    private final TextField name = new TextField("Name");
    private final TextField description = new TextField("Description");
    private final DatePicker dateOfOpen = new DatePicker("Date of open");
    private final Binder<Department> binder = new BeanValidationBinder<>(Department.class);
    private final Button save = new Button("Save");
    private final Button cancel = new Button("Cancel");

    public EditDepartmentModalBox() {
        setClassName("department-edit");
        setHeaderTitle("Edit/create department");
        binder.bindInstanceFields(this);

        setFields();
        setButtons();
    }

    public void setDepartment(Department department) {
        this.department = department;
        binder.setBean(department);
    }

    private void setFields() {
        name.setClearButtonVisible(true);
        description.setClearButtonVisible(true);
        dateOfOpen.setValue(LocalDate.now());

        layout.add(name, description, dateOfOpen);
        add(layout);
    }

    private void setButtons() {
        save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        save.addClickShortcut(Key.ENTER);
        cancel.addClickShortcut(Key.ESCAPE);

        save.addClickListener(event -> validateAndSave());
        cancel.addClickListener(event -> fireEvent(new CloseEvent(this)));

        binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));

        getFooter().add(cancel, save);
    }

    private void validateAndSave() {
        try {
            binder.writeBean(department);
            fireEvent(new SaveEvent(this, department));
        } catch (ValidationException e) {
            throw new RuntimeException(e);
        }
    }

    @Getter
    public static abstract class EditDepartmentEvent
            extends ComponentEvent<EditDepartmentModalBox> {
        private final Department department;

        public EditDepartmentEvent(EditDepartmentModalBox source, Department department) {
            super(source, false);
            this.department = department;
        }
    }

    public static class SaveEvent extends EditDepartmentEvent {
        public SaveEvent(EditDepartmentModalBox source, Department department) {
            super(source, department);
        }
    }

    public static class CloseEvent extends EditDepartmentEvent {
        public CloseEvent(EditDepartmentModalBox source) {
            super(source, null);
        }
    }

    public <T extends ComponentEvent<?>> Registration addListener(Class<T> eventType,
                                                                  ComponentEventListener<T> listener) {
        return getEventBus().addListener(eventType, listener);
    }
}
